package cn.com.kh;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.*;
import java.io.File;
import java.io.FileOutputStream;
import java.util.*;

public class SendBatchMail {
	private static final Log log = LogFactory.getLog(SendBatchMail.class);

	public static List goSendMail(String host, int port, String sendAdderss, String username, String password, List<Map<String, Object>> sendList) {
		// 输出要发送调用信息
		long tstartTime, tendTime, startTime, endTime, estartTime, eendTime;
		tstartTime = System.currentTimeMillis();
		log.debug("开始批量发送邮件,配置参数信息:Start time:" + tstartTime + "-host:" + host + "-port:" + port + "-sendAdderss:" + sendAdderss + "-username:" + username + "-password:" + password);

		// 定义发送结果集
		List resultList = sendList;
		Map<String, Object> resultMap = new HashMap<String, Object>();

		// 连接邮件服务器的参数配置
		Properties properties = new Properties();
		properties.put("mail.transport.protocol", "smtp");
		properties.put("mail.smtp.auth", "true");
		properties.put("mail.smtp.host", host);
		properties.put("mail.smtp.port", port);

		// 设置系统对附件名处理方式
		System.setProperty("mail.mime.splitlongparameters", "false");

		// 创建Session对象
		Session session = Session.getInstance(properties);

		// 设置调试信息在控制台打印出来
		session.setDebug(true);

		Transport transport = null;
		try {

			startTime = System.currentTimeMillis();

			try {
				// 根据session对象获取邮件传输对象Transport
				transport = session.getTransport();

				// 设置发件人的账户名和密码
				transport.connect(username, password);
				endTime = System.currentTimeMillis();
			} catch (Exception e) {
				throw new RunException("SendMail获取邮件传输对象Transport异常!本批次邮件发送全部失败!");
			}

			log.debug("获取邮件传输对象Transport,并建立连接Start time:" + startTime + "; End time:" + endTime + "; Run Time:" + (endTime - startTime) + "(ms)");

			Map<String, Object> receviceMap = new HashMap<String, Object>();
			String rec_guid = null;
			String receviceAddress = null;
			String ccUser = null;
			String bccUser = null;
			String subject = null;
			String content = null;
			String emlFilePath = null;

			String batch_id = null;
			String contenttype = null;
			String pipe = null;
			String relativepath = null;
			String trialcount = null;
			String trialcountlimit = null;

			List attachmentList = new ArrayList();

			// 初始化邮件推送结果
			Boolean sendResult = false;
			Boolean attachResult = false;

			log.debug("开始循环推送邮件,总任务数量:" + sendList.size());
			for (int i = 0; i < sendList.size(); i++) {

				sendResult = false;
				attachResult = false;

				try {
					startTime = System.currentTimeMillis();
					// 创建邮件的实例对象
					MimeMessage message = new MimeMessage(session);
					message.setFrom(new InternetAddress(sendAdderss));

					receviceMap = sendList.get(i);
					resultMap = receviceMap;

					try {
						rec_guid = receviceMap.get("rec_guid").toString();
						receviceAddress = receviceMap.get("receviceAddress").toString();
						ccUser = receviceMap.get("ccUser").toString();
						bccUser = receviceMap.get("bccUser").toString();
						subject = receviceMap.get("subject").toString();
						content = receviceMap.get("content").toString();
						emlFilePath = receviceMap.get("emlFilePath").toString();
						receviceAddress = receviceMap.get("receviceAddress").toString();
						attachmentList = (List<?>) receviceMap.get("attachmentList");

						batch_id = receviceMap.get("batch_id").toString();
						contenttype = receviceMap.get("contenttype").toString();
						pipe = receviceMap.get("pipe").toString();
						relativepath = receviceMap.get("relativepath").toString();
						trialcount = receviceMap.get("trialcount").toString();
						trialcountlimit = receviceMap.get("trialcountlimit").toString();

					} catch (Exception e) {
						throw new RunException("SendMail获取邮件信息异常,请检查List Map信息:" + receviceMap.toString());
					}

					log.debug("Rec_Guid[" + rec_guid + "]-SendMail开始推送邮件(" + i + ")信息" + "-receviceAddress:" + receviceAddress + "-subject:" + subject + "-content:" + content + "-emlFilePath:" + emlFilePath + "-attachmentList:" + attachmentList);

					//message.setRecipients(RecipientType.TO, new InternetAddress[] { new InternetAddress(receviceAddress) });
					// 设置多个收件地址
					if (null != receviceAddress && !receviceAddress.isEmpty()) {
						@SuppressWarnings("static-access")
						InternetAddress[] internetAddressCC = new InternetAddress().parse(receviceAddress);
						message.setRecipients(RecipientType.TO, internetAddressCC);
					}
					
					// 设置多个抄送地址
					if (null != ccUser && !ccUser.isEmpty()) {
						@SuppressWarnings("static-access")
						InternetAddress[] internetAddressCC = new InternetAddress().parse(ccUser);
						message.setRecipients(RecipientType.CC, internetAddressCC);
					}

					// 设置多个密送地址
					if (null != bccUser && !bccUser.isEmpty()) {
						@SuppressWarnings("static-access")
						InternetAddress[] internetAddressBCC = new InternetAddress().parse(bccUser);
						message.setRecipients(RecipientType.BCC, internetAddressBCC);
					}

					message.setSubject(subject, "UTF-8");
					MimeMultipart msgMultipart = new MimeMultipart("mixed");
					MimeBodyPart mbpContent = new MimeBodyPart();

					// 判断处理邮件格式类型
					if ("html".equals(contenttype)) {
						mbpContent.setContent(content, "text/html;charset=utf-8");
					} else {
						mbpContent.setText(content);
					}
					msgMultipart.addBodyPart(mbpContent);

					// 处理邮件附件List
					if (attachmentList != null && attachmentList.size() > 0 && !attachmentList.isEmpty()) {
						for (int j = 0; j < attachmentList.size(); ++j) {
							MimeBodyPart attachment = new MimeBodyPart();
							DataHandler dh = new DataHandler(new FileDataSource((String) attachmentList.get(j)));
							attachment.setDataHandler(dh);
							attachment.setFileName(MimeUtility.encodeWord(dh.getName()));
							msgMultipart.addBodyPart(attachment);
						}
					}

					message.setContent(msgMultipart);

					attachResult = writeEml(session, message, emlFilePath, rec_guid);

					// 发送邮件
					estartTime = System.currentTimeMillis();
					transport.sendMessage(message, message.getAllRecipients());

					eendTime = System.currentTimeMillis();

					log.debug("Rec_Guid[" + rec_guid + "]-SendMail开始传送邮件-Start time:" + estartTime + "; End time:" + eendTime + "; Run Time:" + (eendTime - estartTime) + "(ms)");

					sendResult = true;

				} catch (Exception e) {
					sendResult = false;
					log.warn("Rec_Guid[" + rec_guid + "]-SendMail当前推送邮件Exception:", e);

				} finally {

					resultMap.put("sendResult", sendResult);
					resultMap.put("attachResult", attachResult);

					resultList.set(i, resultMap);

					endTime = System.currentTimeMillis();

					log.debug("Rec_Guid[" + rec_guid + "]-SendMail发送邮件结束,推送Start time:" + startTime + "; End time:" + endTime + "; Run Time:" + (endTime - startTime) + "(ms)");
				}

			}

			transport.close();
			log.debug("全部任务推送End,关闭连接对象Transport完成!");

		} catch (Exception e) {
			log.error("批量发送异常！", e);

		} finally {
			if (null != transport) {
				try {
					transport.close();
					log.debug("成功关闭会话");
				} catch (Exception e) {
					transport = null;
					log.warn("关闭会话警告(忽略)");
				}
			}
		}

		tendTime = System.currentTimeMillis();
		log.debug("批量发送邮件结束 End time:" + tendTime + "; Run Time:" + (tendTime - tstartTime) + "(ms)");
		return resultList;

	}

	public static boolean writeEml(Session session, MimeMessage message, String emlFilePath, String rec_guid) {

		long tstartTime, tendTime, startTime, endTime;

		tstartTime = System.currentTimeMillis();
		log.debug("Rec_Guid[" + rec_guid + "]-File写入本地文件参数 Start time:" + tstartTime + "-emlFilePath:" + emlFilePath + "-message:" + message);

		// 将文件内容写入本地服务器
		int i = 0;
		File dirAll = new File(emlFilePath);

		do {
			startTime = System.currentTimeMillis();
			FileOutputStream fos = null;
			log.debug("Rec_Guid[" + rec_guid + "]-File[" + i + "]开始将文件内容写入本地服务器:" + "-emlFilePath:" + emlFilePath + "-message:" + message);
			try {
				// 文件夹路径是否存在不存在则创建
				File dir = new File(dirAll.getParent());
				if (!dir.exists()) {
					log.debug("Rec_Guid[" + rec_guid + "]-File[" + i + "]创建EML所需路径:" + dirAll.getParent());
					dir.mkdirs();
				}

				// 检查目标文件是否存在，不存在则创建
				if (!dirAll.exists()) {
					log.debug("Rec_Guid[" + rec_guid + "]-File[" + i + "]创建写入EML文件:" + dirAll.getName());
					dirAll.createNewFile();
				}
				// 向目标文件中写入内容
				fos = new FileOutputStream(dirAll);
				try {
					message.writeTo(fos);
				} catch (MessagingException e) {
					log.error("Rec_Guid[" + rec_guid + "]-File[" + i + "]写入EML文件失败...", e);
				}
				log.debug("Rec_Guid[" + rec_guid + "]-File[" + i + "]写入EML文件完成...");

			} catch (Exception e) {
				log.error("Rec_Guid[" + rec_guid + "]-File[" + i + "]写入EML文件失败：", e);
				e.printStackTrace();
			} finally {
				if (null != fos) {
					try {
						fos.close();
					} catch (Exception e) {
						log.error("Rec_Guid[" + rec_guid + "]-File[" + i + "]关闭文件流失败：", e);
					}
				}

				endTime = System.currentTimeMillis();

				log.debug("Rec_Guid[" + rec_guid + "]-File[" + i + "]写入文件结束 Start time:" + startTime + "; End time:" + endTime + "; Run Time:" + (endTime - startTime) + "(ms)");

				i++;

			}
		} while (!dirAll.exists() && i < 3);

		tendTime = System.currentTimeMillis();
		log.debug("Rec_Guid[" + rec_guid + "]-File写入本地文件结束 End time:" + tendTime + "; Run Time:" + (tendTime - tstartTime) + "(ms)");

		return dirAll.exists();

	}

}

class RunException extends Exception {
	/**
	 * RunException
	 */
	private static final long serialVersionUID = 1L;

	public RunException(String msg) {
		super(msg);
	}
}